package com.zhou.spring.cloud.balancer.exception;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.zhou.spring.cloud.balancer.util.I18nUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {


    private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${spring.profiles.active:production}")
    private String profile;

    @Autowired
    private HttpServletRequest request;


    @ResponseStatus()
    @ExceptionHandler(Exception.class)
    public Response handleException(Exception e) {
        logger.error("", e);
        return new Response(999, e.getMessage());
    }

    /**
     * 处理自定义异常
     */
    @ResponseStatus()
    @ExceptionHandler(BizException.class)
    public Response<String> handleMessageException(BizException e) {
        String message = e.getMessage();
        if (StringUtils.isNotEmpty(e.getMessageKey())) {
            message = I18nUtil.getMessage(e.getMessageKey(), e.getArgs(), e.getMessageKey(), request.getLocale());
        }
        logger.error(String.format("[%s] : %s,%s, ip : {}", request.getRequestURI(), e.getMessageKey(), message),
                getIpAddress());
        return new Response(e.getCode(), message);
    }

    @ResponseStatus()
    @ExceptionHandler({MethodArgumentNotValidException.class,
            BindException.class})
    public Response<String> handleArgumentException(BindException e) {

        BindingResult result = e.getBindingResult();

        List<FieldError> fieldErrors = result.getFieldErrors();

        StringBuilder message = new StringBuilder();
        fieldErrors.forEach(t -> {
            message.append(t.getField() + ":" + t.getDefaultMessage() + " ");
        });
        logger.error(String.format("[%s] : %s, ip : {}", request.getRequestURI(), message),
                getIpAddress(), e);
        return new Response(999, message.toString());
    }

    private String getIpAddress() {
        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
